#!/usr/bin/env python
# -*- coding: UTF-8 -*-
"""
@Project ：python_learning 
@File ：日志并发处理.py
@IDE  ：PyCharm 
@Author ：李涵彬
@Date ：2025/2/19 下午11:48 
"""

import logging
import multiprocessing
from logging.handlers import QueueHandler, QueueListener
import time

# 修改日志队列初始化方式
formatter = logging.Formatter('%(asctime)s | %(levelname)-8s | PID %(process)-6d | %(message)s')

def setup_logging(log_queue):
	"""配置日志系统（接收队列参数）"""
	# 文件日志处理器
	file_handler = logging.FileHandler('output.log', encoding='utf-8')
	file_handler.setFormatter(formatter)
	
	# 控制台日志处理器
	console_handler = logging.StreamHandler()
	console_handler.setFormatter(formatter)
	
	# 使用传入的队列
	listener = QueueListener(log_queue, file_handler, console_handler)
	listener.start()
	return listener

def worker(task_id, log_queue):
	"""带异常处理的工作进程"""
	logger = logging.getLogger()
	# 简化日志配置（Windows下需要重新配置）
	if not logger.handlers:
		logger.setLevel(logging.INFO)
		logger.addHandler(QueueHandler(log_queue))
	
	try:
		print(f"Task {task_id} started.")
		logger.info(f"Task {task_id} started.")
		time.sleep(2 * (task_id % 2 + 1))  # 更真实的模拟不同时长任务
		if task_id == 3:  # 模拟异常情况
			raise ValueError("模拟任务3出现错误")
		logger.info(f"Task {task_id} completed successfully.")
	except Exception as e:
		logger.error(f"Task {task_id} failed: {str(e)}", exc_info=True)

def run_concurrent_tasks(main_queue):
	# 创建进程池时使用主队列
	with multiprocessing.Pool(processes=5) as pool:
		# 直接使用主队列，不再创建新队列
		pool.starmap(worker, [(i, main_queue) for i in range(5)])

if __name__ == '__main__':
	multiprocessing.freeze_support()
	manager = multiprocessing.Manager()
	main_queue = manager.Queue()  # 主队列唯一创建点
	listener = setup_logging(main_queue)
	try:
		run_concurrent_tasks(main_queue)  # 传递主队列给任务
	finally:
		listener.stop()
